package utils

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/tls"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/patrickmn/go-cache"
	"github.com/spf13/cast"
	"io/ioutil"
	"net/http"
	"regexp"
	"strings"
	"time"
)

var cacheClient *cache.Cache

func init() {
	cacheClient = cache.New(10*time.Second, 30*time.Second)
}

//通讯录应用
func CgiBinCommunicateGettoken() (token string, error error) {
	v1, found := cacheClient.Get("workWeChatCommunicateAccessToken")
	if found {
		//fmt.Println("缓存")
		return cast.ToString(v1), nil
	}
	corpid := "ww6d4b9533d27ed59d"
	corpsecret := "5KXe_hlj3j_DB9UgLvcrcUPWFbrx1Iv10NIufYnwoQk" //通讯录秘钥
	url := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s", corpid, corpsecret)
	method := "GET"
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		return "", err
	}
	res, err := client.Do(req)
	if err != nil {
		return "", err
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return "", err
	}
	//fmt.Println(string(body))
	resBody := make(map[string]interface{})
	err = json.Unmarshal(body, &resBody)
	if err != nil {
		return "", err
	}
	if cast.ToInt64(resBody["errcode"]) != 0 {
		return "", errors.New(fmt.Sprintf("errcode:%d", cast.ToInt64(resBody["errcode"])))
	}
	cacheClient.Set("workWeChatCommunicateAccessToken", cast.ToString(resBody["access_token"]), 7200*time.Second)
	//fmt.Println("生成")
	return cast.ToString(resBody["access_token"]), nil
}

//自建应用缓存token
func CgiBinGettoken() (token string, error error) {
	// 从缓存中获取与 key "foo" 关联的字符串
	v1, found := cacheClient.Get("workWeChatAccessToken")
	if found {
		//fmt.Println("缓存")
		return cast.ToString(v1), nil
	}
	corpid := "ww6d4b9533d27ed59d"
	corpsecret := "-pkRmNniY4vE-blbQiUnH8YW_6n47lU-lGPeH9bCTOY"
	url := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s", corpid, corpsecret)
	method := "GET"
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		return "", err
	}
	res, err := client.Do(req)
	if err != nil {
		return "", err
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return "", err
	}
	//fmt.Println(string(body))
	resBody := make(map[string]interface{})
	err = json.Unmarshal(body, &resBody)
	if err != nil {
		return "", err
	}
	if cast.ToInt64(resBody["errcode"]) != 0 {
		return "", errors.New(fmt.Sprintf("errcode:%d", cast.ToInt64(resBody["errcode"])))
	}
	cacheClient.Set("workWeChatAccessToken", cast.ToString(resBody["access_token"]), 7200*time.Second)
	//fmt.Println("生成")
	return cast.ToString(resBody["access_token"]), nil
}

//获取访问用户身份
func CgiBinAuthGetuserinfo(code string) (token string, error error) {
	token, err := CgiBinGettoken()
	if err != nil {
		return "", err
	}
	url := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token=%s&code=%s", token, code)
	method := "GET"
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		return "", err
	}
	res, err := client.Do(req)
	if err != nil {
		return "", err
	}
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return "", err
	}
	fmt.Println(string(body))

	resBody := make(map[string]interface{})
	err = json.Unmarshal(body, &resBody)
	if err != nil {
		return "", err
	}
	if cast.ToInt64(resBody["errcode"]) != 0 {
		return "", errors.New(fmt.Sprintf("errcode:%d", cast.ToInt64(resBody["errcode"])))
	}
	return cast.ToString(resBody["user_ticket"]), nil
}

//获取访问用户敏感信息
type CgiBinAuthGetuserdetailStruct struct {
	Errcode int    `json:"errcode"`
	Errmsg  string `json:"errmsg"`
	Userid  string `json:"userid"`
	Gender  string `json:"gender"`
	Avatar  string `json:"avatar"`
	QrCode  string `json:"qr_code"`
	Mobile  string `json:"mobile"`
	Email   string `json:"email"`
	BizMail string `json:"biz_mail"`
	Address string `json:"address"`
}

func CgiBinAuthGetuserdetail(postbytes []byte) (datas CgiBinAuthGetuserdetailStruct, error error) {
	token, err := CgiBinGettoken()
	if err != nil {
		return CgiBinAuthGetuserdetailStruct{}, err
	}
	url := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/auth/getuserdetail?access_token=?access_token=%s", token)
	method := "POST"
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}
	req, err := http.NewRequest(method, url, bytes.NewBuffer(postbytes))
	if err != nil {
		return CgiBinAuthGetuserdetailStruct{}, err
	}
	res, err := client.Do(req)
	if err != nil {
		return CgiBinAuthGetuserdetailStruct{}, err
	}
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return CgiBinAuthGetuserdetailStruct{}, err
	}
	fmt.Println(string(body))

	resBody := CgiBinAuthGetuserdetailStruct{}
	err = json.Unmarshal(body, &resBody)
	if err != nil {
		return CgiBinAuthGetuserdetailStruct{}, err
	}
	if cast.ToInt64(resBody.Errcode) != 0 {
		return CgiBinAuthGetuserdetailStruct{}, errors.New(fmt.Sprintf("errcode:%d", cast.ToInt64(resBody.Errmsg)))
	}
	return resBody, nil
}

//导出成员任务
func ExportUser() (jobid string, error error) {
	token, err := CgiBinGettoken()
	if err != nil {
		return "", err
	}
	url := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/export/user?access_token=%s", token)
	method := "POST"
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}
	payload := strings.NewReader(`{"encoding_aeskey": "IJUiXNpvGbODwKEBSEsAeOAPAhkqHqNCF6g19t9wfg2","block_size": 1000000}`)
	req, err := http.NewRequest(method, url, payload)
	if err != nil {
		return "", err
	}
	res, err := client.Do(req)
	if err != nil {
		return "", err
	}
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return "", err
	}
	fmt.Println(string(body))

	resBody := make(map[string]interface{})
	err = json.Unmarshal(body, &resBody)
	if err != nil {
		return "", err
	}
	if cast.ToInt64(resBody["errcode"]) != 0 {
		return "", errors.New(fmt.Sprintf("errcode:%d", cast.ToInt64(resBody["errcode"])))
	}
	return cast.ToString(resBody["jobid"]), nil
}

//导出部门
func ExportDepartment() (jobid string, error error) {
	token, err := CgiBinGettoken()
	if err != nil {
		return "", err
	}
	url := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/export/department?access_token=%s", token)
	method := "POST"
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}
	payload := strings.NewReader(`{"encoding_aeskey": "IJUiXNpvGbODwKEBSEsAeOAPAhkqHqNCF6g19t9wfg2","block_size": 1000000}`)
	req, err := http.NewRequest(method, url, payload)
	if err != nil {
		return "", err
	}
	res, err := client.Do(req)
	if err != nil {
		return "", err
	}
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return "", err
	}
	fmt.Println(string(body))

	resBody := make(map[string]interface{})
	err = json.Unmarshal(body, &resBody)
	if err != nil {
		return "", err
	}
	if cast.ToInt64(resBody["errcode"]) != 0 {
		return "", errors.New(fmt.Sprintf("errcode:%d", cast.ToInt64(resBody["errcode"])))
	}
	return cast.ToString(resBody["jobid"]), nil
}

//获取任务结果
type ExportGetResultStruct struct {
	Url  string `json:"url"`
	Size int    `json:"size"`
	Md5  string `json:"md5"`
}

//任务详情获取
func ExportGetResult(jobid string) (data []ExportGetResultStruct, error error) {
	token, err := CgiBinGettoken()
	if err != nil {
		return nil, err
	}
	url := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/export/get_result?access_token=%s&jobid=%s", token, jobid)
	method := "GET"
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		return nil, err
	}
	res, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}
	//fmt.Println(string(body))

	resBody := make(map[string]interface{})
	err = json.Unmarshal(body, &resBody)
	if err != nil {
		return nil, err
	}
	if cast.ToInt64(resBody["errcode"]) != 0 {
		return nil, errors.New(fmt.Sprintf("errcode:%d", cast.ToInt64(resBody["errcode"])))
	}

	dataList, err := json.Marshal(resBody["data_list"])
	if err != nil {
		return nil, err
	}

	exportGetResult := []ExportGetResultStruct{}
	err = json.Unmarshal(dataList, &exportGetResult)
	if err != nil {
		return nil, err
	}

	return exportGetResult, nil
}

//解析下载内容
func AesDecodeContent(url string) (resBody []byte, err error) {
	encodingAeskey := "IJUiXNpvGbODwKEBSEsAeOAPAhkqHqNCF6g19t9wfg2=" //密钥值
	method := "GET"
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		return nil, err
	}
	res, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	bodyByte, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}

	aeskey, err := base64.StdEncoding.DecodeString(encodingAeskey)
	if nil != err {
		return nil, err
	}

	block, err := aes.NewCipher(aeskey)
	if err != nil {
		return nil, err
	}
	if len(bodyByte) < aes.BlockSize {
		return nil, err
	}
	iv := aeskey[:aes.BlockSize]
	if len(bodyByte)%aes.BlockSize != 0 {
		return nil, err
	}
	mode := cipher.NewCBCDecrypter(block, iv)
	mode.CryptBlocks(bodyByte, bodyByte)

	re := regexp.MustCompile(`{(.*)}`)
	regBody := re.FindString(string(bodyByte))

	return []byte(regBody), nil
}

//获取打卡月报数据
type CheckinGetcheckinMonthdataStruct struct {
	Errcode int    `json:"errcode"`
	Errmsg  string `json:"errmsg"`
	Datas   []struct {
		BaseInfo struct {
			RecordType  int    `json:"record_type"`
			Name        string `json:"name"`
			NameEx      string `json:"name_ex"`
			DepartsName string `json:"departs_name"`
			RuleInfo    struct {
				Groupid     int           `json:"groupid"`
				Groupname   string        `json:"groupname"`
				Checkintime []interface{} `json:"checkintime"`
			} `json:"rule_info"`
			Acctid string `json:"acctid"`
		} `json:"base_info"`
		SummaryInfo struct {
			WorkDays        int `json:"work_days"`
			RegularDays     int `json:"regular_days"`
			ExceptDays      int `json:"except_days"`
			RegularWorkSec  int `json:"regular_work_sec"`
			StandardWorkSec int `json:"standard_work_sec"`
		} `json:"summary_info"`
		ExceptionInfos []struct {
			Count     int `json:"count"`
			Duration  int `json:"duration"`
			Exception int `json:"exception"`
		} `json:"exception_infos"`
		SpItems []struct {
			Type       int    `json:"type"`
			VacationId int    `json:"vacation_id"`
			Count      int    `json:"count"`
			Duration   int    `json:"duration"`
			TimeType   int    `json:"time_type"`
			Name       string `json:"name"`
		} `json:"sp_items"`
		OverworkInfo struct {
			WorkdayOverSec         int `json:"workday_over_sec"`
			HolidaysOverSec        int `json:"holidays_over_sec"`
			RestdaysOverSec        int `json:"restdays_over_sec"`
			WorkdaysOverAsVacation int `json:"workdays_over_as_vacation"`
			WorkdaysOverAsMoney    int `json:"workdays_over_as_money"`
			RestdaysOverAsVacation int `json:"restdays_over_as_vacation"`
			RestdaysOverAsMoney    int `json:"restdays_over_as_money"`
			HolidaysOverAsVacation int `json:"holidays_over_as_vacation"`
			HolidaysOverAsMoney    int `json:"holidays_over_as_money"`
		} `json:"overwork_info"`
	} `json:"datas"`
}

func CheckinGetcheckinMonthdata(postbytes []byte) (datas CheckinGetcheckinMonthdataStruct, error error) {
	token, err := CgiBinGettoken()
	if err != nil {
		return CheckinGetcheckinMonthdataStruct{}, err
	}
	url := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckin_monthdata?access_token=%s", token)
	method := "POST"
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	req, err := http.NewRequest(method, url, bytes.NewBuffer(postbytes))
	if err != nil {
		return CheckinGetcheckinMonthdataStruct{}, err
	}
	res, err := client.Do(req)
	if err != nil {
		return CheckinGetcheckinMonthdataStruct{}, err
	}
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return CheckinGetcheckinMonthdataStruct{}, err
	}

	resBody := CheckinGetcheckinMonthdataStruct{}

	err = json.Unmarshal(body, &resBody)
	if err != nil {
		return CheckinGetcheckinMonthdataStruct{}, err
	}
	if cast.ToInt64(resBody.Errcode) != 0 {
		return CheckinGetcheckinMonthdataStruct{}, errors.New(fmt.Sprintf("errcode:%d", cast.ToInt64(resBody.Errmsg)))
	}
	return resBody, nil
}

type CheckinGetcheckindataStruct struct {
	Errcode     int    `json:"errcode"`
	Errmsg      string `json:"errmsg"`
	Checkindata []struct {
		Userid         string   `json:"userid"`
		Groupname      string   `json:"groupname"`
		CheckinType    string   `json:"checkin_type"`
		ExceptionType  string   `json:"exception_type"`
		CheckinTime    int      `json:"checkin_time"`
		LocationTitle  string   `json:"location_title"`
		LocationDetail string   `json:"location_detail"`
		Wifiname       string   `json:"wifiname"`
		Notes          string   `json:"notes"`
		Wifimac        string   `json:"wifimac"`
		Mediaids       []string `json:"mediaids"`
		SchCheckinTime int      `json:"sch_checkin_time"`
		Groupid        int      `json:"groupid"`
		ScheduleId     int      `json:"schedule_id"`
		TimelineId     int      `json:"timeline_id"`
		Lat            int      `json:"lat,omitempty"`
		Lng            int      `json:"lng,omitempty"`
		Deviceid       string   `json:"deviceid,omitempty"`
	} `json:"checkindata"`
}

func CheckinGetcheckindata(postbytes []byte) (datas CheckinGetcheckindataStruct, error error) {
	token, err := CgiBinGettoken()
	if err != nil {
		return CheckinGetcheckindataStruct{}, err
	}
	url := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckindata?access_token=%s", token)
	method := "POST"
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	fmt.Println(url)

	fmt.Println(string(postbytes))

	req, err := http.NewRequest(method, url, bytes.NewBuffer(postbytes))
	if err != nil {
		return CheckinGetcheckindataStruct{}, err
	}
	res, err := client.Do(req)
	if err != nil {
		return CheckinGetcheckindataStruct{}, err
	}
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return CheckinGetcheckindataStruct{}, err
	}

	fmt.Println(string(body))
	resBody := CheckinGetcheckindataStruct{}

	err = json.Unmarshal(body, &resBody)
	if err != nil {
		return CheckinGetcheckindataStruct{}, err
	}
	if cast.ToInt64(resBody.Errcode) != 0 {
		return CheckinGetcheckindataStruct{}, errors.New(fmt.Sprintf("errcode:%d", cast.ToInt64(resBody.Errmsg)))
	}
	return resBody, nil
}

type CheckinGetcheckinDaydataStruct struct {
	Errcode int    `json:"errcode"`
	Errmsg  string `json:"errmsg"`
	Datas   []struct {
		BaseInfo struct {
			Date        int    `json:"date"`
			RecordType  int    `json:"record_type"`
			Name        string `json:"name"`
			NameEx      string `json:"name_ex"`
			DepartsName string `json:"departs_name"`
			Acctid      string `json:"acctid"`
			RuleInfo    struct {
				Groupid     int    `json:"groupid"`
				Groupname   string `json:"groupname"`
				Scheduleid  int    `json:"scheduleid"`
				Checkintime []struct {
					WorkSec    int `json:"work_sec"`
					OffWorkSec int `json:"off_work_sec"`
				} `json:"checkintime"`
				Schedulename string `json:"schedulename,omitempty"`
			} `json:"rule_info"`
			DayType int `json:"day_type"`
		} `json:"base_info"`
		SummaryInfo struct {
			CheckinCount   int `json:"checkin_count"`
			RegularWorkSec int `json:"regular_work_sec"`
			//StandardWorkSec int `json:"standard_work_sec"`
			EarliestTime int `json:"earliest_time"`
			LastestTime  int `json:"lastest_time"`
		} `json:"summary_info"`
		HolidayInfos []struct {
			SpNumber string `json:"sp_number"`
			SpTitle  struct {
				Data []struct {
					Text string `json:"text"`
					Lang string `json:"lang"`
				} `json:"data"`
			} `json:"sp_title"`
			SpDescription struct {
				Data []struct {
					Text string `json:"text"`
					Lang string `json:"lang"`
				} `json:"data"`
			} `json:"sp_description"`
		} `json:"holiday_infos"`
		ExceptionInfos []struct {
			Count     int `json:"count"`
			Duration  int `json:"duration"`
			Exception int `json:"exception"`
		} `json:"exception_infos"`
		OtInfo struct {
			OtStatus          int           `json:"ot_status"`
			OtDuration        int           `json:"ot_duration"`
			ExceptionDuration []interface{} `json:"exception_duration"`
		} `json:"ot_info"`
		SpItems []struct {
			Type       int    `json:"type"`
			VacationId int    `json:"vacation_id"`
			Count      int    `json:"count"`
			Duration   int    `json:"duration"`
			TimeType   int    `json:"time_type"`
			Name       string `json:"name"`
		} `json:"sp_items"`
	} `json:"datas"`
}

func CheckinGetcheckinDaydata(postbytes []byte) (datas CheckinGetcheckinDaydataStruct, error error) {
	token, err := CgiBinGettoken()
	if err != nil {
		return CheckinGetcheckinDaydataStruct{}, err
	}
	url := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckin_daydata?access_token=%s", token)
	method := "POST"
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	req, err := http.NewRequest(method, url, bytes.NewBuffer(postbytes))
	if err != nil {
		return CheckinGetcheckinDaydataStruct{}, err
	}
	res, err := client.Do(req)
	if err != nil {
		return CheckinGetcheckinDaydataStruct{}, err
	}
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return CheckinGetcheckinDaydataStruct{}, err
	}

	resBody := CheckinGetcheckinDaydataStruct{}

	err = json.Unmarshal(body, &resBody)
	if err != nil {
		return CheckinGetcheckinDaydataStruct{}, err
	}
	if cast.ToInt64(resBody.Errcode) != 0 {
		return CheckinGetcheckinDaydataStruct{}, errors.New(fmt.Sprintf("errcode:%d", cast.ToInt64(resBody.Errmsg)))
	}
	return resBody, nil
}

type CheckinGetcorpcheckinoptionStruct struct {
	Errcode int    `json:"errcode"`
	Errmsg  string `json:"errmsg"`
	Group   []struct {
		Grouptype   int `json:"grouptype"`
		Groupid     int `json:"groupid"`
		Checkindate []struct {
			Workdays    []int `json:"workdays"`
			Checkintime []struct {
				WorkSec          int `json:"work_sec"`
				OffWorkSec       int `json:"off_work_sec"`
				RemindWorkSec    int `json:"remind_work_sec"`
				RemindOffWorkSec int `json:"remind_off_work_sec"`
			} `json:"checkintime"`
			NoneedOffwork   bool `json:"noneed_offwork"`
			LimitAheadtime  int  `json:"limit_aheadtime"`
			FlexOnDutyTime  int  `json:"flex_on_duty_time"`
			FlexOffDutyTime int  `json:"flex_off_duty_time"`
		} `json:"checkindate"`
		SpeWorkdays []struct {
			Timestamp   int    `json:"timestamp"`
			Notes       string `json:"notes"`
			Checkintime []struct {
				WorkSec          int `json:"work_sec"`
				OffWorkSec       int `json:"off_work_sec"`
				RemindWorkSec    int `json:"remind_work_sec"`
				RemindOffWorkSec int `json:"remind_off_work_sec"`
			} `json:"checkintime"`
		} `json:"spe_workdays"`
		SpeOffdays []struct {
			Timestamp   int           `json:"timestamp"`
			Notes       string        `json:"notes"`
			Checkintime []interface{} `json:"checkintime"`
		} `json:"spe_offdays"`
		SyncHolidays bool   `json:"sync_holidays"`
		Groupname    string `json:"groupname"`
		NeedPhoto    bool   `json:"need_photo"`
		WifimacInfos []struct {
			Wifiname string `json:"wifiname"`
			Wifimac  string `json:"wifimac"`
		} `json:"wifimac_infos"`
		NoteCanUseLocalPic     bool `json:"note_can_use_local_pic"`
		AllowCheckinOffworkday bool `json:"allow_checkin_offworkday"`
		AllowApplyOffworkday   bool `json:"allow_apply_offworkday"`
		LocInfos               []struct {
			Lat       int    `json:"lat"`
			Lng       int    `json:"lng"`
			LocTitle  string `json:"loc_title"`
			LocDetail string `json:"loc_detail"`
			Distance  int    `json:"distance"`
		} `json:"loc_infos"`
		Range struct {
			PartyId []interface{} `json:"party_id"`
			Userid  []string      `json:"userid"`
			Tagid   []int         `json:"tagid"`
		} `json:"range"`
		CreateTime   int      `json:"create_time"`
		WhiteUsers   []string `json:"white_users"`
		Type         int      `json:"type"`
		Reporterinfo struct {
			Reporters []struct {
				Userid string `json:"userid"`
			} `json:"reporters"`
			Updatetime int `json:"updatetime"`
		} `json:"reporterinfo"`
		OtInfo struct {
			Type                 int  `json:"type"`
			AllowOtWorkingday    bool `json:"allow_ot_workingday"`
			AllowOtNonworkingday bool `json:"allow_ot_nonworkingday"`
			Otcheckinfo          struct {
				OtWorkingdayTimeStart  int `json:"ot_workingday_time_start"`
				OtWorkingdayTimeMin    int `json:"ot_workingday_time_min"`
				OtWorkingdayTimeMax    int `json:"ot_workingday_time_max"`
				OtNonworkingdayTimeMin int `json:"ot_nonworkingday_time_min"`
				OtNonworkingdayTimeMax int `json:"ot_nonworkingday_time_max"`
				OtWorkingdayRestinfo   struct {
					Type        int `json:"type"`
					FixTimeRule struct {
						FixTimeBeginSec int `json:"fix_time_begin_sec"`
						FixTimeEndSec   int `json:"fix_time_end_sec"`
					} `json:"fix_time_rule"`
					CalOttimeRule struct {
						Items []struct {
							OtTime   int `json:"ot_time"`
							RestTime int `json:"rest_time"`
						} `json:"items"`
					} `json:"cal_ottime_rule"`
				} `json:"ot_workingday_restinfo"`
				OtNonworkingdayRestinfo struct {
					Type        int `json:"type"`
					FixTimeRule struct {
						FixTimeBeginSec int `json:"fix_time_begin_sec"`
						FixTimeEndSec   int `json:"fix_time_end_sec"`
					} `json:"fix_time_rule"`
					CalOttimeRule struct {
						Items []struct {
							OtTime   int `json:"ot_time"`
							RestTime int `json:"rest_time"`
						} `json:"items"`
					} `json:"cal_ottime_rule"`
				} `json:"ot_nonworkingday_restinfo"`
				OtNonworkingdaySpandayTime int `json:"ot_nonworkingday_spanday_time"`
			} `json:"otcheckinfo"`
			Uptime      int `json:"uptime"`
			Otapplyinfo struct {
				AllowOtWorkingday    bool `json:"allow_ot_workingday"`
				AllowOtNonworkingday bool `json:"allow_ot_nonworkingday"`
				Uptime               int  `json:"uptime"`
				OtWorkingdayRestinfo struct {
					Type        int `json:"type"`
					FixTimeRule struct {
						FixTimeBeginSec int `json:"fix_time_begin_sec"`
						FixTimeEndSec   int `json:"fix_time_end_sec"`
					} `json:"fix_time_rule"`
					CalOttimeRule struct {
						Items []struct {
							OtTime   int `json:"ot_time"`
							RestTime int `json:"rest_time"`
						} `json:"items"`
					} `json:"cal_ottime_rule"`
				} `json:"ot_workingday_restinfo"`
				OtNonworkingdayRestinfo struct {
					Type        int `json:"type"`
					FixTimeRule struct {
						FixTimeBeginSec int `json:"fix_time_begin_sec"`
						FixTimeEndSec   int `json:"fix_time_end_sec"`
					} `json:"fix_time_rule"`
					CalOttimeRule struct {
						Items []struct {
							OtTime   int `json:"ot_time"`
							RestTime int `json:"rest_time"`
						} `json:"items"`
					} `json:"cal_ottime_rule"`
				} `json:"ot_nonworkingday_restinfo"`
				OtNonworkingdaySpandayTime int `json:"ot_nonworkingday_spanday_time"`
			} `json:"otapplyinfo"`
		} `json:"ot_info"`
		AllowApplyBkCnt      int    `json:"allow_apply_bk_cnt"`
		OptionOutRange       int    `json:"option_out_range"`
		CreateUserid         string `json:"create_userid"`
		UseFaceDetect        bool   `json:"use_face_detect"`
		AllowApplyBkDayLimit int    `json:"allow_apply_bk_day_limit"`
		UpdateUserid         string `json:"update_userid"`
		Schedulelist         []struct {
			ScheduleId   int    `json:"schedule_id"`
			ScheduleName string `json:"schedule_name"`
			TimeSection  []struct {
				TimeId           int  `json:"time_id"`
				WorkSec          int  `json:"work_sec"`
				OffWorkSec       int  `json:"off_work_sec"`
				RemindWorkSec    int  `json:"remind_work_sec"`
				RemindOffWorkSec int  `json:"remind_off_work_sec"`
				RestBeginTime    int  `json:"rest_begin_time"`
				RestEndTime      int  `json:"rest_end_time"`
				AllowRest        bool `json:"allow_rest"`
			} `json:"time_section"`
			LimitAheadtime  int  `json:"limit_aheadtime"`
			NoneedOffwork   bool `json:"noneed_offwork"`
			LimitOfftime    int  `json:"limit_offtime"`
			FlexOnDutyTime  int  `json:"flex_on_duty_time"`
			FlexOffDutyTime int  `json:"flex_off_duty_time"`
			AllowFlex       bool `json:"allow_flex"`
			LateRule        struct {
				AllowOffworkAfterTime bool `json:"allow_offwork_after_time"`
				Timerules             []struct {
					OffworkAfterTime int `json:"offwork_after_time"`
					OnworkFlexTime   int `json:"onwork_flex_time"`
				} `json:"timerules"`
			} `json:"late_rule"`
			MaxAllowArriveEarly int `json:"max_allow_arrive_early"`
			MaxAllowArriveLate  int `json:"max_allow_arrive_late"`
		} `json:"schedulelist"`
		OffworkIntervalTime int `json:"offwork_interval_time"`
	} `json:"group"`
}

func CheckinGetcorpcheckinoption() (datas CheckinGetcorpcheckinoptionStruct, error error) {
	token, err := CgiBinGettoken()
	if err != nil {
		return CheckinGetcorpcheckinoptionStruct{}, err
	}
	url := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/checkin/getcorpcheckinoption?access_token=%s", token)
	method := "POST"
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	req, err := http.NewRequest(method, url, bytes.NewBuffer([]byte("{}")))
	if err != nil {
		return CheckinGetcorpcheckinoptionStruct{}, err
	}
	res, err := client.Do(req)
	if err != nil {
		return CheckinGetcorpcheckinoptionStruct{}, err
	}
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return CheckinGetcorpcheckinoptionStruct{}, err
	}

	resBody := CheckinGetcorpcheckinoptionStruct{}

	err = json.Unmarshal(body, &resBody)
	if err != nil {
		return CheckinGetcorpcheckinoptionStruct{}, err
	}
	if cast.ToInt64(resBody.Errcode) != 0 {
		return CheckinGetcorpcheckinoptionStruct{}, errors.New(fmt.Sprintf("errcode:%d", cast.ToInt64(resBody.Errmsg)))
	}
	return resBody, nil
}

type CheckinGetcheckinschedulistStruct struct {
	ScheduleList []struct {
		Userid    string `json:"userid"`
		Yearmonth int    `json:"yearmonth"`
		Groupid   int    `json:"groupid"`
		Groupname string `json:"groupname"`
		Schedule  struct {
			ScheduleList []struct {
				Day          int `json:"day"`
				ScheduleInfo struct {
					ScheduleId   int    `json:"schedule_id"`
					ScheduleName string `json:"schedule_name"`
					TimeSection  []struct {
						Id               int `json:"id"`
						WorkSec          int `json:"work_sec"`
						OffWorkSec       int `json:"off_work_sec"`
						RemindWorkSec    int `json:"remind_work_sec"`
						RemindOffWorkSec int `json:"remind_off_work_sec"`
					} `json:"time_section"`
				} `json:"schedule_info"`
			} `json:"scheduleList"`
		} `json:"schedule"`
	} `json:"schedule_list"`
	Errcode int    `json:"errcode"`
	Errmsg  string `json:"errmsg"`
}

func CheckinGetcheckinschedulist(postbytes []byte) (datas CheckinGetcheckinschedulistStruct, error error) {
	token, err := CgiBinGettoken()
	if err != nil {
		return CheckinGetcheckinschedulistStruct{}, err
	}
	url := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckinschedulist?access_token=%s", token)
	method := "POST"
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	req, err := http.NewRequest(method, url, bytes.NewBuffer(postbytes))
	if err != nil {
		return CheckinGetcheckinschedulistStruct{}, err
	}
	res, err := client.Do(req)
	if err != nil {
		return CheckinGetcheckinschedulistStruct{}, err
	}
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return CheckinGetcheckinschedulistStruct{}, err
	}

	resBody := CheckinGetcheckinschedulistStruct{}

	err = json.Unmarshal(body, &resBody)
	if err != nil {
		return CheckinGetcheckinschedulistStruct{}, err
	}
	if cast.ToInt64(resBody.Errcode) != 0 {
		return CheckinGetcheckinschedulistStruct{}, errors.New(fmt.Sprintf("errcode:%d", cast.ToInt64(resBody.Errmsg)))
	}
	return resBody, nil
}

type CheckinGetcheckinoptionStruct struct {
	Errcode int    `json:"errcode"`
	Errmsg  string `json:"errmsg"`
	Info    []struct {
		Userid string `json:"userid"`
		Group  struct {
			Grouptype   int `json:"grouptype"`
			Groupid     int `json:"groupid"`
			Checkindate []struct {
				Workdays    []int `json:"workdays"`
				Checkintime []struct {
					WorkSec          int `json:"work_sec"`
					OffWorkSec       int `json:"off_work_sec"`
					RemindWorkSec    int `json:"remind_work_sec"`
					RemindOffWorkSec int `json:"remind_off_work_sec"`
				} `json:"checkintime"`
				FlexTime        int  `json:"flex_time"`
				NoneedOffwork   bool `json:"noneed_offwork"`
				LimitAheadtime  int  `json:"limit_aheadtime"`
				FlexOnDutyTime  int  `json:"flex_on_duty_time"`
				FlexOffDutyTime int  `json:"flex_off_duty_time"`
			} `json:"checkindate"`
			SpeWorkdays []struct {
				Timestamp   int    `json:"timestamp"`
				Notes       string `json:"notes"`
				Checkintime []struct {
					WorkSec          int `json:"work_sec"`
					OffWorkSec       int `json:"off_work_sec"`
					RemindWorkSec    int `json:"remind_work_sec"`
					RemindOffWorkSec int `json:"remind_off_work_sec"`
				} `json:"checkintime"`
			} `json:"spe_workdays"`
			SpeOffdays []struct {
				Timestamp   int           `json:"timestamp"`
				Notes       string        `json:"notes"`
				Checkintime []interface{} `json:"checkintime"`
			} `json:"spe_offdays"`
			SyncHolidays bool   `json:"sync_holidays"`
			Groupname    string `json:"groupname"`
			NeedPhoto    bool   `json:"need_photo"`
			WifimacInfos []struct {
				Wifiname string `json:"wifiname"`
				Wifimac  string `json:"wifimac"`
			} `json:"wifimac_infos"`
			NoteCanUseLocalPic     bool `json:"note_can_use_local_pic"`
			AllowCheckinOffworkday bool `json:"allow_checkin_offworkday"`
			AllowApplyOffworkday   bool `json:"allow_apply_offworkday"`
			LocInfos               []struct {
				Lat       int    `json:"lat"`
				Lng       int    `json:"lng"`
				LocTitle  string `json:"loc_title"`
				LocDetail string `json:"loc_detail"`
				Distance  int    `json:"distance"`
			} `json:"loc_infos"`
			Schedulelist []struct {
				ScheduleId   int    `json:"schedule_id"`
				ScheduleName string `json:"schedule_name"`
				TimeSection  []struct {
					TimeId           int  `json:"time_id"`
					WorkSec          int  `json:"work_sec"`
					OffWorkSec       int  `json:"off_work_sec"`
					RemindWorkSec    int  `json:"remind_work_sec"`
					RemindOffWorkSec int  `json:"remind_off_work_sec"`
					RestBeginTime    int  `json:"rest_begin_time"`
					RestEndTime      int  `json:"rest_end_time"`
					AllowRest        bool `json:"allow_rest"`
				} `json:"time_section"`
				LimitAheadtime  int  `json:"limit_aheadtime"`
				NoneedOffwork   bool `json:"noneed_offwork"`
				LimitOfftime    int  `json:"limit_offtime"`
				FlexOnDutyTime  int  `json:"flex_on_duty_time"`
				FlexOffDutyTime int  `json:"flex_off_duty_time"`
				AllowFlex       bool `json:"allow_flex"`
				LateRule        struct {
					AllowOffworkAfterTime bool `json:"allow_offwork_after_time"`
					Timerules             []struct {
						OffworkAfterTime int `json:"offwork_after_time"`
						OnworkFlexTime   int `json:"onwork_flex_time"`
					} `json:"timerules"`
				} `json:"late_rule"`
				MaxAllowArriveEarly int `json:"max_allow_arrive_early"`
				MaxAllowArriveLate  int `json:"max_allow_arrive_late"`
			} `json:"schedulelist"`
		} `json:"group"`
	} `json:"info"`
}

func CheckinGetcheckinoption(postbytes []byte) (datas CheckinGetcheckinoptionStruct, error error) {
	token, err := CgiBinGettoken()
	if err != nil {
		return CheckinGetcheckinoptionStruct{}, err
	}
	url := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/checkin/getcheckinoption?access_token=%s", token)
	method := "POST"
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	req, err := http.NewRequest(method, url, bytes.NewBuffer(postbytes))
	if err != nil {
		return CheckinGetcheckinoptionStruct{}, err
	}
	res, err := client.Do(req)
	if err != nil {
		return CheckinGetcheckinoptionStruct{}, err
	}
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return CheckinGetcheckinoptionStruct{}, err
	}

	resBody := CheckinGetcheckinoptionStruct{}

	err = json.Unmarshal(body, &resBody)
	if err != nil {
		return CheckinGetcheckinoptionStruct{}, err
	}
	if cast.ToInt64(resBody.Errcode) != 0 {
		return CheckinGetcheckinoptionStruct{}, errors.New(fmt.Sprintf("errcode:%d", cast.ToInt64(resBody.Errmsg)))
	}
	return resBody, nil
}

type ExmailAppCcomposeSendStruct struct {
	Errcode int    `json:"errcode"`
	Errmsg  string `json:"errmsg"`
}

func ExmailAppCcomposeSend(postbytes []byte) (datas ExmailAppCcomposeSendStruct, error error) {
	token, err := CgiBinGettoken()
	if err != nil {
		return ExmailAppCcomposeSendStruct{}, err
	}
	url := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/exmail/app/compose_send?access_token=%s", token)
	method := "POST"
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	fmt.Println(string(postbytes))

	req, err := http.NewRequest(method, url, bytes.NewBuffer(postbytes))
	if err != nil {
		return ExmailAppCcomposeSendStruct{}, err
	}
	res, err := client.Do(req)
	if err != nil {
		return ExmailAppCcomposeSendStruct{}, err
	}
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return ExmailAppCcomposeSendStruct{}, err
	}

	fmt.Println(string(body))

	resBody := ExmailAppCcomposeSendStruct{}

	err = json.Unmarshal(body, &resBody)
	if err != nil {
		return ExmailAppCcomposeSendStruct{}, err
	}
	if cast.ToInt64(resBody.Errcode) != 0 {
		return ExmailAppCcomposeSendStruct{}, errors.New(fmt.Sprintf("errcode:%d", cast.ToInt64(resBody.Errmsg)))
	}
	return resBody, nil
}

type GetApprovalInfoDataStruct struct {
	Errcode  int      `json:"errcode"`
	Errmsg   string   `json:"errmsg"`
	SpNoList []string `json:"sp_no_list"`
}

func GetApprovalInfoData(postbytes []byte) (datas GetApprovalInfoDataStruct, error error) {
	token, err := CgiBinGettoken()
	if err != nil {
		return GetApprovalInfoDataStruct{}, err
	}
	url := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovalinfo?access_token=%s", token)
	method := "POST"
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	fmt.Println(url)

	fmt.Println(string(postbytes))

	req, err := http.NewRequest(method, url, bytes.NewBuffer(postbytes))
	if err != nil {
		return GetApprovalInfoDataStruct{}, err
	}
	res, err := client.Do(req)
	if err != nil {
		return GetApprovalInfoDataStruct{}, err
	}
	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return GetApprovalInfoDataStruct{}, err
	}

	fmt.Println(string(body))
	resBody := GetApprovalInfoDataStruct{}

	err = json.Unmarshal(body, &resBody)
	if err != nil {
		return GetApprovalInfoDataStruct{}, err
	}
	if cast.ToInt64(resBody.Errcode) != 0 {
		return GetApprovalInfoDataStruct{}, errors.New(fmt.Sprintf("errcode:%d", cast.ToInt64(resBody.Errmsg)))
	}
	return resBody, nil
}
